package instances

import (
	"encoding/json"
	"fmt"
	"gluenet/pkg/apis"
	"gluenet/pkg/meta"
	"strings"
)

const queryConfig = "select * from config where label = ?"

func CreateInstance(ctx *apis.GlueContext) {
	var (
		err error
		req = struct {
			Kind         string `json:"kind"`
			Mode         string `json:"mode"`
			ConfigLabel  string `json:"config_label"`
			InstanceName string `json:"instance_name"`
		}{}
	)
	if err = ctx.WebContext.ReadJSON(&req); err != nil {
		ctx.WebContext.JSON(apis.ResponseReqErr(err, nil))
		return
	}

	ctx.Logger.Debugf("revice create instance %v", req)

	// 校验config label
	if err = ctx.Validate.Label(req.ConfigLabel, req.Kind, req.Mode, meta.KindConfig); err != nil {
		e := fmt.Errorf("validate label %v", err)
		ctx.WebContext.JSON(apis.ResponseReqErr(e, nil))
		ctx.Logger.Errorf("%v", e)
		return
	}
	if err = ctx.Validate.Name(req.InstanceName, req.Kind, req.Mode, meta.KindInstance); err != nil {
		e := fmt.Errorf("validate label %v", err)
		ctx.WebContext.JSON(apis.ResponseReqErr(e, nil))
		ctx.Logger.Errorf("%v", e)
		return
	}

	//查询config
	var cfgs *meta.Config
	if err = ctx.DataBase.ConfigGet(req.Mode, req.ConfigLabel, &cfgs); err != nil {
		ctx.Logger.Errorf("query error:%v, or data is nil", err)
		ctx.WebContext.JSON(apis.ResponseReqErr(fmt.Errorf("query error:%v, or data is nil", err), nil))
		return
	}

	//注册guid
	var guid string
	cfgs.Name = req.InstanceName
	cfgs.Label = req.ConfigLabel
	if guid, err = registerGuid(ctx, cfgs); err != nil {
		ctx.Logger.Errorf("register guid %v", err)
		ctx.WebContext.JSON(apis.ResponseReqErr(fmt.Errorf("register gui %v", err), nil))
		return
	}

	//初始化实例配置
	var ins = meta.Instance{Guid: guid, Name: req.InstanceName, Platform: cfgs.Platform, Label: strings.Replace(req.ConfigLabel, meta.KindConfig, meta.KindInstance, 1)}
	if ins.InstanceValue, err = apis.CreateInstanceFromConfig(cfgs.ConfigValue, req.InstanceName, guid, req.Mode, req.Kind); err != nil {
		ctx.Logger.Errorf("init instance value from config %v", err)
		ctx.WebContext.JSON(apis.ResponseReqErr(fmt.Errorf("init instance value from config %v", err), nil))
		return
	}

	//存储数据
	if _, err = ctx.DataBase.MetaDB().InsertOne(ins); err != nil {
		ctx.Logger.Errorf("impl instance %v", err)
		ctx.WebContext.JSON(apis.ResponseReqErr(fmt.Errorf("impl instance %v", err), nil))
		return
	}
	var irun = meta.InstanceRunTime{
		AppGuid:     guid,
		AppPlatform: cfgs.Platform,
	}
	if err = ctx.DataBase.InstanceRuntimePut(&irun); err != nil {
		ctx.Logger.Errorf("imput runtime instance %v", err)
		ctx.WebContext.JSON(apis.ResponseReqErr(fmt.Errorf("imput runtime instance %v", err), nil))
		return
	}

	//发配调度
	if err = scheduleReq(ctx, ins); err != nil {
		ctx.Logger.Errorf("shedule req %v", err)
		ctx.WebContext.JSON(apis.ResponseReqErr(fmt.Errorf("shedule req %v", err), nil))
		return
	}
	ctx.WebContext.JSON(apis.ResponseOK(nil))
}

func registerGuid(ctx *apis.GlueContext, data interface{}) (string, error) {
	var req = apis.IRequest{Data: data}
	bts, _ := json.Marshal(req)
	bts, err := ctx.Rpc.Request(apis.GuidServiceRegister, bts)
	if err != nil {
		return "", err
	}
	resp := apis.IResponse{}
	if err = json.Unmarshal(bts, &resp); err != nil {
		return "", err
	}
	return resp.Data.(string), nil
}

func scheduleReq(ctx *apis.GlueContext, data interface{}) error {
	var req = apis.IEvent{Data: data}
	bts, _ := json.Marshal(req)
	err := ctx.Rpc.Publish(apis.SchedulerServiceSchedule, bts)
	if err != nil {
		return err
	}
	return nil
}
